package org.dromara.web.service.impl

import cn.dev33.satoken.stp.StpUtil
import io.github.oshai.kotlinlogging.KotlinLogging
import org.dromara.common.core.domain.model.EmailLoginBody
import org.dromara.common.core.domain.model.LoginUser
import org.dromara.common.core.enums.LoginType
import org.dromara.common.core.utils.ValidatorUtils.validate
import org.dromara.common.json.utils.JsonUtils
import org.dromara.common.satoken.utils.LoginHelper
import org.dromara.common.tenant.helper.TenantHelper
import org.dromara.system.domain.SysUser
import org.dromara.system.domain.vo.SysClientVo
import org.dromara.system.mapper.SysUserMapper
import org.dromara.web.domain.vo.LoginVo
import org.dromara.web.service.IAuthStrategy
import org.dromara.web.service.SysLoginService
import org.springframework.stereotype.Service

/**
 * 邮件认证策略
 *
 *@author LikeYouDo
 *@date 2025/1/3 09:46
 */
@Service("email" + IAuthStrategy.BASE_NAME)
class EmailAuthStrategy(
    private val loginService: SysLoginService,
    private val userMapper: SysUserMapper,
) : IAuthStrategy {

    companion object {
        private val log = KotlinLogging.logger {}
    }

    override fun login(body: String, client: SysClientVo): LoginVo {
        val loginBody = JsonUtils.parseObject(body, EmailLoginBody::class.java)
        validate(loginBody)
        val tenantId = loginBody.tenantId
        val email = loginBody.email
        val emailCode = loginBody.emailCode
        val loginUser = TenantHelper.dynamic<LoginUser>(tenantId) {
            val user = loadUserByCondition(userMapper, SysUser::getEmail, email, log)
            loginService.checkLogin(LoginType.EMAIL, tenantId, user.userName) {
                !validateCode(loginService, tenantId, email, emailCode)
            }
            // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
            loginService.buildLoginUser(user)
        }.apply {
            clientKey = client.clientKey
            deviceType = client.deviceType
        }
        val model = createSaLoginModel(client)
        // 生成token
        LoginHelper.login(loginUser, model)

        val loginVo = LoginVo().apply {
            accessToken = StpUtil.getTokenValue()
            expireIn = StpUtil.getTokenTimeout()
            clientId = client.clientId
        }
        return loginVo
    }

}
